#pragma once
#include <string>
#include <map>
#include <memory>
#include <nlohmann/json.hpp>
namespace cpp_backend
{
    namespace framework
    {
        /**
         * @brief 统一请求对象
         * 封装来自不同协议(HTTP, Websocket, RPC)
         * 的请求数据
         */
        class Request
        {
        public:
            Request() = default;
            ~Request() = default;
            /**
             * @brief 设置请求方法
             */
            void SetMethod(const std::string &method)
            {
                method_ = method;
            }
            const std::string &GetMethod() const
            {
                return method_;
            }

            /**
             * @brief 设置请求路径
             */
            void SetPath(const std::string &path)
            {
                path_ = path;
            }
            const std::string &GetPath() const
            {
                return path_;
            }

            /**
             * @brief 设置请求头
             */
            void SetHeader(const std::string &key, const std::string &value)
            {
                headers_[key] = value;
            }
            std::string GetHeader(const std::string &key) const
            {
                auto it = headers_.find(key);
                return it != headers_.end() ? it->second : "";
            }
            const std::map<std::string, std::string> &GetHeaders() const
            {
                return headers_;
            }

            /**
             * @brief 设置请求参数（Query/Form）
             */
            void SetParam(const std::string &key, const std::string &value)
            {
                params_[key] = value;
            }
            std::string GetParam(const std::string &key) const
            {
                auto it = params_.find(key);
                return it != params_.end() ? it->second : "";
            }
            const std::map<std::string, std::string> &GetParams() const
            {
                return params_;
            }
            /** @brief 设置请求体 */
            void SetBody(const nlohmann::json &body)
            {
                body_ = body;
            }
            const nlohmann::json &GetBody() const
            {
                return body_;
            }
            /** @brief 设置原始请求体(二进制) */
            void SetRawBody(const std::vector<uint8_t> &raw_body)
            {
                raw_body_ = raw_body;
            }
            const std::vector<uint8_t> &GetRawBody() const
            {
                return raw_body_;
            }

            /**
             * @brief 设置用户ID(认证后)
             */
            void SetUserId(int64_t user_id)
            {
                user_id_ = user_id;
            }
            int64_t GetUserId() const
            {
                return user_id_;
            }
            /**
             * @brief 设置用户名(认证后)
             */
            void SetUserName(const std::string &user_name)
            {
                user_name_ = user_name;
            }
            const std::string &GetUserName() const
            {
                return this->user_name_;
            }

            /**
             * @brief 设置用户角色(认证后)
             */
            void SetUserRole(const std::string &user_role)
            {
                this->user_role_ = user_role;
            }
            const std::string &GetUserRole() const
            {
                return this->user_role_;
            }
            /**
             * @brief 是否已认证
             */
            bool IsAuthenticated() const
            {
                return this->user_id_ > 0;
            }
            /**
             * @brief 设置客户端IP
             */
            void SetClientIp(const std::string &ip)
            {
                this->client_ip_ = ip;
            }
            const std::string &GetClientIp() const
            {
                return this->client_ip_;
            }
            /**
             * @brief 获取请求ID(用于链路追踪)
             */
            void SetRequestId(const std::string &request_id)
            {
                this->request_id_ = request_id;
            }
            const std::string &GetRequestId() const
            {
                return this->request_id_;
            }

            /**
             * @brief 设置自定义属性（扩展用）
             */
            void SetAttribute(const std::string &key, const std::string &value)
            {
                this->attributes_[key] = value;
            }
            std::string GetAttribute(const std::string &key) const
            {
                auto it = this->attributes_.find(key);
                return it != this->attributes_.end() ? it->second : "";
            }
            /**
             * @brief 转换为JSON(用于日志)
             */
            nlohmann::json ToJson() const
            {
                nlohmann::json j;
                j["method"] = this->method_;
                j["path"] = this->path_;
                j["user_id"] = this->user_id_;
                j["user_name"] = this->user_name_;
                j["client_ip"] = this->client_ip_;
                j["request_id"] = this->request_id_;
                j["headers"] = this->headers_;
                j["params"] = this->params_;
                j["body"] = this->body_;
                j["attributes"] = this->attributes_;
                return j;
            }

        private:
            std::string method_;                         // 请求方法(GET/POST/PUT/DELETE)
            std::string path_;                           // 请求路径
            std::map<std::string, std::string> headers_; // 请求头
            std::map<std::string, std::string> params_;  // 请求参数
            nlohmann::json body_;                        // 请求体
            std::vector<uint8_t> raw_body_;              // 原始请求体(二进制)
            // 认证信息
            int64_t user_id_ = 0;
            std::string user_name_;
            std::string user_role_;
            // 元信息
            std::string client_ip_;
            std::string request_id_;
            std::map<std::string, std::string> attributes_; // 自定义属性
        };
        using RequestPtr = std::shared_ptr<Request>;
    }
}
